﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace NetManagerSystem.Components
{
    /// <summary>
    /// Console.xaml 的交互逻辑
    /// </summary>
    public partial class Console : UserControl
    {
        public static string LineChar = "\r\n";
        /// <summary>
        /// 获取头文件的委托
        /// </summary>
        /// <returns></returns>
        public delegate string GetHeaderTextHandle();
        /// <summary>
        /// 按下某个按键的委托
        /// </summary>
        /// <param name="e"></param>
        public delegate void PressKeyHandle(KeyEventArgs e);
        /// <summary>
        /// 通过此方法获取HeaderText
        /// </summary>
        public event GetHeaderTextHandle GetHeaderText;
        /// <summary>
        /// 按下某个按键
        /// </summary>
        public event PressKeyHandle PressKey;
        /// <summary>
        /// 行头文本
        /// </summary>
        private string HeaderText { get; set; }
        /// <summary>
        /// 当前输入的命令
        /// </summary>
        public string Command { get; set; }
        /// <summary>
        /// 历史命令列表
        /// </summary>
        private List<string> HistoryCommand = new List<string>();
        /// <summary>
        /// 当前命令索引位置
        /// </summary>
        private int CommandIndex = 0;
        /// <summary>
        /// 光标位置与行头结束位置的偏移，偏移大于0，光标位置小于行头
        /// </summary>
        private int CaretAndHeaderEnd
        {
            get
            {
                // 当前光标不在输入范围内
                var CaretPosition = rtxtMain.CaretPosition;
                var index = rtxtMain.Document.ContentEnd.GetPositionAtOffset(-1 * this.Command.Length - 2);
                return CaretPosition.GetOffsetToPosition(index);
            }
        }
        /// <summary>
        /// 获取最后一行内容
        /// </summary>
        private string LastLine
        {
            get
            {
                var text = new TextRange(rtxtMain.Document.ContentStart, rtxtMain.Document.ContentEnd).Text;
                var lineChar = "\r\n";
                if (text.EndsWith(LineChar))
                {
                    text = text.Substring(0, text.Length - LineChar.Length);
                }
                var index = text.LastIndexOf(lineChar);
                return index >= 0 ? text.Substring(index+ lineChar.Length) : text;
            }
        }
        /// <summary>
        /// 行头长度
        /// </summary>
        private int HeaderTextLength
        {
            get { return string.IsNullOrEmpty(HeaderText) ? 0 : HeaderText.Length; }
        }
        public Console()
        {
            InitializeComponent();
            rtxtMain.Document.LineHeight = 1;
            rtxtMain.Foreground = new SolidColorBrush(Color.FromRgb(0, 255, 128));
            rtxtMain.Background = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            rtxtMain.PreviewKeyDown += RtxtMain_PreviewKeyDown;
        }

        /// <summary>
        /// 写出行头文件
        /// </summary>
        public void writeHeaderText()
        {
            this.CaretToEnd();
            this.HeaderText = GetHeaderText?.Invoke();
            this.write(this.HeaderText, end: "");
        }
        /// <summary>
        /// 移动光标到结尾
        /// </summary>
        public void CaretToEnd()
        {
            rtxtMain.CaretPosition = rtxtMain.CaretPosition.DocumentEnd;
        }

        private void RtxtMain_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            // 先给属性command赋值
            var range = new TextRange(rtxtMain.Document.ContentStart, rtxtMain.Document.ContentEnd);
            var cmd = range.Text.Substring(range.Text.LastIndexOf(HeaderText) + HeaderText.Length);
            bool CaretToEnd = true;
            if (cmd.EndsWith(LineChar))
            {
                cmd = cmd.Substring(0, cmd.Length - LineChar.Length);
            }
            Command = cmd;
            // 解析按下的按键
            if (e.Key == Key.Return)
            {
                // 按下回车
                e.Handled = true; // 取消事件
                this.CaretToEnd();
                saveCommand();
                this.write();
                PressKey?.Invoke(e);
                this.writeHeaderText();
            }
            if (e.Key == Key.Tab)
            {
                // 按下tab键
                this.CaretToEnd();
                e.Handled = true; // 取消事件
                PressKey?.Invoke(e);
            }
            if (e.Key == Key.OemQuestion && e.KeyboardDevice.Modifiers == ModifierKeys.Shift)
            {
                // 按下SHIFT+？
                this.CaretToEnd();
                e.Handled = true;
                write("?");
                PressKey.Invoke(e);
                writeHeaderText();
                write(Command, end: "");
            }
            if (e.Key == Key.Back)
            {
                // 按下Backspace
                this.CaretToEnd();
                if(LastLine.Length <= HeaderTextLength)
                {
                    e.Handled = true;
                }
            }
            if(e.Key == Key.Up)
            {
                e.Handled = true;
                PreviousCommand();
            }
            if (e.Key == Key.Down)
            {
                e.Handled = true;
                NextCommand();
            }
            if (e.Key == Key.Home)
            {
                CaretToEnd = false;
                e.Handled = true;
                PressHome();
            }
            if(e.Key == Key.Left)
            {
                CaretToEnd = false;
                if (CaretAndHeaderEnd > -1)
                {
                    e.Handled = true;
                }
            }
            if(e.Key == Key.Escape || e.Key == Key.F1 || e.Key == Key.Right || e.Key == Key.LeftShift || e.Key == Key.RightShift)
            {
                CaretToEnd = false;
            }
            if (CaretToEnd)
            {
                if(CaretAndHeaderEnd > 0)
                {
                    this.CaretToEnd();
                }
            }
        }
        /// <summary>
        /// 按下home键
        /// </summary>
        private void PressHome()
        {
            var index = rtxtMain.Document.ContentEnd.GetPositionAtOffset(-1 * this.Command.Length - 2);
            rtxtMain.CaretPosition = index;
        }

        /// <summary>
        /// 记录命令
        /// </summary>
        private void saveCommand()
        {
            if (!string.IsNullOrEmpty(this.Command))
            {
                HistoryCommand.Add(this.Command);
                CommandIndex = HistoryCommand.Count;
            }
        }
        /// <summary>
        /// 下一个命令
        /// </summary>
        private void NextCommand()
        {
            if(CommandIndex + 1 >= 0 && CommandIndex + 1 < HistoryCommand.Count)
            {
                CommandIndex++;
                updateCommand(HistoryCommand[CommandIndex]);
            }
        }
        /// <summary>
        /// 替换命令
        /// </summary>
        /// <param name="newCommand"></param>
        private void updateCommand(string newCommand)
        {
            if (!string.IsNullOrEmpty(this.Command))
            {
                TextRange tr = new TextRange(rtxtMain.Document.ContentStart, rtxtMain.Document.ContentEnd);
                var text = tr.Text;
                // 获取到最后一个header的索引
                var headerIndex = text.LastIndexOf(this.HeaderText);
                tr.Text = text.Substring(0, headerIndex + HeaderText.Length) + newCommand;
            }
            else
            {
                write(newCommand, "");
            }
            this.Command = newCommand;
        }
        /// <summary>
        /// 上一个命令
        /// </summary>
        private void PreviousCommand()
        {
            if (CommandIndex - 1 >=0 && CommandIndex - 1 < HistoryCommand.Count)
            {
                CommandIndex--;
                updateCommand(HistoryCommand[CommandIndex]);
            }
        }

        /// <summary>
        /// 写入一行内容
        /// </summary>
        /// <param name="info">待写入的内容</param>
        public void write(string info = "", string end = "\n")
        {
            rtxtMain.AppendText(info + end);
            this.CaretToEnd();
            rtxtMain.ScrollToEnd();
        }
    }
}